package com.mch.main.tools;

import java.lang.management.ClassLoadingMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;

public class JVMResource {

	public static void main(String[] args) {
		new JVMResource().printSummary();
	}

	private NumberFormat fmtI = new DecimalFormat("###,###", new DecimalFormatSymbols(Locale.ENGLISH));
	private NumberFormat fmtD = new DecimalFormat("###,##0.000", new DecimalFormatSymbols(Locale.ENGLISH));

	private final int Kb = 1024;

	public String printSummary() {
		StringBuilder sb = new StringBuilder();
		RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
		OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
		ThreadMXBean threads = ManagementFactory.getThreadMXBean();
		MemoryMXBean mem = ManagementFactory.getMemoryMXBean();
		ClassLoadingMXBean cl = ManagementFactory.getClassLoadingMXBean();
		sb.append(String.format("JVM Name:%s %s %s%n", runtime.getVmName(), "version", runtime.getVmVersion()));
		sb.append(String.format("JVM Java Ver:%s%n", System.getProperty("java.version")));
		sb.append(String.format("JVM Vendor:%s%n", runtime.getVmVendor()));
		sb.append(String.format("JVM Uptime:%s%n", toDuration(runtime.getUptime())));
		sb.append(String.format("threadsLive:%d%n", threads.getThreadCount()));
		sb.append(String.format("threadsDaemon:%d%n", threads.getDaemonThreadCount()));
		sb.append(String.format("threadsPeak:%d%n", threads.getPeakThreadCount()));
		sb.append(String.format("threadsTotal:%d%n", threads.getTotalStartedThreadCount()));
		sb.append(String.format("heapCurr:%d%n", mem.getHeapMemoryUsage().getUsed() / Kb));
		sb.append(String.format("heapMax:%d%n", mem.getHeapMemoryUsage().getMax() / Kb));
		sb.append(String.format("heapCommitted:%d%n", mem.getHeapMemoryUsage().getCommitted() / Kb));
		sb.append(String.format("osName:%s %s %s%n", os.getName(), "version", os.getVersion()));
		sb.append(String.format("osArch:%s%n", os.getArch()));
		sb.append(String.format("osCores:%s%n", os.getAvailableProcessors()));
		sb.append(String.format("clsCurrLoaded:%s%n", cl.getLoadedClassCount()));
		sb.append(String.format("clsLoaded:%s%n", cl.getTotalLoadedClassCount()));
		sb.append(String.format("clsUnloaded:%s%n", cl.getUnloadedClassCount()));

		return sb.toString();
	}

	protected String printSizeInKb(double size) {
		return fmtI.format((long) (size / 1024)) + " kbytes";
	}

	protected String toDuration(double uptime) {
		uptime /= 1000;
		if (uptime < 60) {
			return fmtD.format(uptime) + " seconds";
		}
		uptime /= 60;
		if (uptime < 60) {
			long minutes = (long) uptime;
			String s = fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute");
			return s;
		}
		uptime /= 60;
		if (uptime < 24) {
			long hours = (long) uptime;
			long minutes = (long) ((uptime - hours) * 60);
			String s = fmtI.format(hours) + (hours > 1 ? " hours" : " hour");
			if (minutes != 0) {
				s += " " + fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute");
			}
			return s;
		}
		uptime /= 24;
		long days = (long) uptime;
		long hours = (long) ((uptime - days) * 24);
		String s = fmtI.format(days) + (days > 1 ? " days" : " day");
		if (hours != 0) {
			s += " " + fmtI.format(hours) + (hours > 1 ? " hours" : " hour");
		}
		return s;
	}

}